from django import forms

from django.forms.widgets import get_default_renderer
from django.core.exceptions import ImproperlyConfigured
from django.utils.safestring import mark_safe
from django.urls import reverse

from .configs import DEFAULT_CONFIG
from django.conf import settings

from . import utils


STRING_VALUE_OPTIONS = [
    "mode", 
    "name", 
    "value", 
    "theme", 
    "editorTheme", 
    "previewTheme", 
    "markdown", 
    "appendMarkdown", 
    "width", 
    "height", 
    "path", 
    "placeholder", 
    "dialogMaskBgColor", 
    "fontSize", 
    "imageUploadURL", 
    "uploadCallbackURL", 
    "tocTitle", 
    "tocContainer", 
    "toolbarIcons", 
    "pluginPath", 
]

OPTIONAL_CONFIGS = ["global", "default"]


class EditorMDWidget(forms.Textarea):
    template_name = 'djmd/edit_widget.html'

    class Media:
        css = {
            "all": ("/static/djmd/css/editormd.css",),
        }

        js = (
            "/static/djmd/editormd.js",
            "/static/djmd/editormd-init.js",
        )

    def __init__(self, config_name='default', include_jquery=True, image_upload_url=None, extra_js_files=None, *args, **kwargs):

        self.preped_config = None

        super(EditorMDWidget, self).__init__(*args, **kwargs)

        if include_jquery:
            # order is important, must load jq before editormd
            self.Media.js = ("/static/djmd/jquery-3.4.1.min.js",) + self.Media.js

        self.config = DEFAULT_CONFIG.copy()

        self._update_configs("global")
        self._update_configs(config_name)


        # image upload url in init args has the highest priority
        if image_upload_url:
            if not isinstance(image_upload_url, str):
                raise ImproperlyConfigured("Image upload url must be a string.")

            self.config["imageUploadURL"] = image_upload_url


        extra_js_files = (
            extra_js_files
            or self.config.pop("extra_js_files", None)
            or ()
        )

        self.Media.js = self.Media.js + extra_js_files


    def _update_configs(self, config_name):
        configs = getattr(settings, 'DJMD_CONFIGS', None)

        if configs:
            if isinstance(configs, dict):
                # Make sure the config_name exists.
                if config_name in configs:
                    config = configs[config_name]
                    # Make sure the configuration is a dictionary.
                    if not isinstance(config, dict):
                        raise ImproperlyConfigured('DJMD_CONFIGS["%s"] \
                                setting must be a dictionary type.' %
                                                   config_name)
                    # Override defaults with settings config.
                    self.config.update(config)
                else:

                    if config_name in OPTIONAL_CONFIGS:
                        return

                    raise ImproperlyConfigured("No configuration named '%s' \
                            found in your DJMD_CONFIGS setting." %
                                               config_name)
            else:
                raise ImproperlyConfigured('DJMD_CONFIGS setting must be a\
                        dictionary type.')



    def render(self, name, value, attrs=None, renderer=None):
        if renderer is None:
            renderer = get_default_renderer()
        if value is None:
            value = ''

        context = self.get_context(name, value, attrs)

        self._prep_config()

        context["config"] = self.preped_config

        return mark_safe(renderer.render(EditorMDWidget.template_name, context))



    def _prep_config(self):

        if not self.preped_config:
            self.preped_config = self.config.copy()

            for key, value in self.preped_config.items():

                if key == "toolbarIcons" and value not in ("full", "simple", "mini"):
                    continue

                if key in ("width", "height") and not isinstance(value, str):
                    continue

                if key in STRING_VALUE_OPTIONS:
                    self.preped_config[key] = '"' + value + '"'



class EditorMDUploadingWidget(EditorMDWidget):

    def render(self, name, value, attrs=None, renderer=None):

        utils.auto_config()

        thread_local_urlconf = getattr(settings, "DJMD_THREAD_LOCAL_URLCONF", None)

        image_upload_url = reverse("djmd_upload", urlconf=thread_local_urlconf)

        self.config.setdefault("imageUploadURL", image_upload_url)
        self.config["imageUpload"] = "true"

        return super().render(name, value, attrs, renderer)


